﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GalaSoft.MvvmLight;
using System.Collections.ObjectModel;
using System.Windows.Media;
using System.Windows;
using System.ComponentModel;

namespace DiagramDesigner
{
    public class DataModel : ObservableObject
    {
        public DataModel()
        {
            SubItems = new ObservableCollection<DataSubItemModel>();
        }
        public ObservableCollection<DataSubItemModel> SubItems { get; private set; }
    }

    public class DataSubItemModel : ObservableObject
    {
        /// <summary>
        /// The <see cref="SubItemCollection" /> property's name.
        /// </summary>
        public const string SubItemCollectionPropertyName = "SubItemCollection";

        private ObservableCollection<PointCollection> _subItemCollection = new ObservableCollection<PointCollection>();

        /// <summary>
        /// Sets and gets the SubItemCollection property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public ObservableCollection<PointCollection> SubItemCollection
        {
            get
            {
                return _subItemCollection;
            }

            set
            {
                if (_subItemCollection == value)
                {
                    return;
                }

                _subItemCollection = value;
                RaisePropertyChanged(SubItemCollectionPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="Substrate" /> property's name.
        /// </summary>
        public const string SubstratePropertyName = "Substrate";

        private LineModel _substrate = null;

        /// <summary>
        /// Sets and gets the Substrate property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public LineModel Substrate
        {
            get
            {
                return _substrate;
            }

            set
            {
                if (_substrate == value)
                {
                    return;
                }
                
                if (_substrate != null)
                    _substrate.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(BindLines);

                _substrate = value;
                
                if (_substrate != null)
                    _substrate.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(BindLines);
                
                BindLines(this, new PropertyChangedEventArgs("Substrate"));

                RaisePropertyChanged(SubstratePropertyName);
            }
        }

        void BindLines(object sender, PropertyChangedEventArgs e)
        {
            if (_angleLineLeft != null && _substrate != null)
                AngleLineLeft.Pt1 = ProjectPoint(_angleLineLeft.Pt1, _substrate);
        }

        /// <summary>
        /// The <see cref="AngleLineLeft" /> property's name.
        /// </summary>
        public const string AngleLineLeftPropertyName = "AngleLineLeft";

        private LineModel _angleLineLeft = null;

        /// <summary>
        /// Sets and gets the AngleLineLeft property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public LineModel AngleLineLeft
        {
            get
            {
                return _angleLineLeft;
            }

            set
            {
                if (_angleLineLeft == value)
                {
                    return;
                }

                if (_angleLineLeft != null)
                    _angleLineLeft.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(BindLines);
                
                _angleLineLeft = value;

                if (_angleLineLeft != null)
                    _angleLineLeft.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(BindLines);

                BindLines(this, new PropertyChangedEventArgs("Substrate"));
                
                RaisePropertyChanged(AngleLineLeftPropertyName);
            }
        }        

        private Point ProjectPoint(Point p, LineModel l)
        {
            Point p1 = l.Pt1;
            Point p2 = l.Pt2;

            //find StartPoint projection onto the substrate
            double fDenominator = (p2.X - p1.X) * (p2.X - p1.X) + (p2.Y - p1.Y) * (p2.Y - p1.Y);

            if (fDenominator == 0) // p1 and p2 are the same
                return p1;

            double t = (p.X * (p2.X - p1.X) - (p2.X - p1.X) * p1.X + p.Y * (p2.Y - p1.Y) - (p2.Y - p1.Y) * p1.Y) / fDenominator;
            if (t < 0)
                t = 0;
            if (t > 1)
                t = 1;

            return new Point(p1.X + (p2.X - p1.X) * t, p1.Y + (p2.Y - p1.Y) * t);
        }
    }

}
